//! 中断设备接口实现
#![feature(lazy_cell)]

use std::{
    collections::HashMap,
    sync::{Arc, LazyLock},
};

use objectid::ObjectId;
use rcu::RcuLock;

/// 中断后端设备
pub struct IntBackendDevice {
    num: u32,
    int_device: Arc<dyn IntBackendImpl + Send + Sync>,
}

impl IntBackendDevice {
    /// 创建一个中断后端设备
    pub fn create(num: u32, int_device: Arc<dyn IntBackendImpl + Send + Sync>) -> Self {
        Self { num, int_device }
    }

    /// 向后端设置一个中断信号
    pub fn set_int(&self, level: bool) {
        self.int_device.set_int(level, self.num);
    }

    /// 向后端设置一个上升沿中断信号
    pub fn int_raise(&self) {
        self.int_device.set_int(true, self.num);
    }

    /// 向后端设置一个下降沿中断信号
    pub fn int_lower(&self) {
        self.int_device.set_int(false, self.num);
    }

    /// 向后端设置一个脉冲中断信号
    pub fn int_pulse(&self) {
        self.int_device.set_int(true, self.num);
        self.int_device.set_int(false, self.num);
    }
}

/// 中断后端设备实现
pub trait IntBackendImpl: ObjectId {
    /// 向后端设置一个中断信号
    fn set_int(&self, level: bool, num: u32);

    /// 向后端设置一个上升沿中断信号
    fn int_raise(&self, num: u32) {
        self.set_int(true, num);
    }

    /// 向后端设置一个下降沿中断信号
    fn int_lower(&self, num: u32) {
        self.set_int(false, num);
    }

    /// 向后端设置一个脉冲中断信号
    fn int_pulse(&self, num: u32) {
        self.set_int(true, num);
        self.set_int(false, num);
    }
}

/// 中断节点
pub struct InterruptNode {
    backend: Arc<IntBackendDevice>,
    child: RcuLock<HashMap<u32, Arc<InterruptNode>>>,
}

impl InterruptNode {
    /// 注册一个中断节点
    #[allow(clippy::missing_panics_doc)]
    #[allow(clippy::arc_with_non_send_sync)]
    pub fn register_int_node(&self, backend: Arc<IntBackendDevice>) -> Arc<Self> {
        let node = Arc::new(InterruptNode { backend, child: RcuLock::new(HashMap::new()) });
        let mut lock = self.child.write().unwrap();
        lock.insert(node.backend.num, node.clone());
        node
    }
}

struct DummpyIntBackendDevice;

impl ObjectId for DummpyIntBackendDevice {
    fn compatible(&self) -> &'static str {
        "root_int_node"
    }

    fn id(&self) -> &str {
        "root_int_node"
    }
}

impl IntBackendImpl for DummpyIntBackendDevice {
    fn set_int(&self, _: bool, _: u32) {}
}

static ROOT_INT_NODE: LazyLock<Arc<InterruptNode>> = LazyLock::new(|| {
    let root = IntBackendDevice::create(0, Arc::new(DummpyIntBackendDevice));
    Arc::new(InterruptNode { backend: Arc::new(root), child: RcuLock::new(HashMap::new()) })
});

/// 全局根中断节点
pub fn root_int() -> Arc<InterruptNode> {
    ROOT_INT_NODE.clone()
}
